import matplotlib.pyplot as plt
from mpmath import  mp,mpf,exp,pi

# 设置多精度浮点数的精度
mp.dps = 50  # 可以根据需要调整精度

# 显示5个不同版本的exp(x)的 Remez 近似多项式的误差 和 glibc中 exp函数的误差
def glibc_exp_error(x):
    C0=mpf("1.0")
    C1=mpf("1.0")
    C2=mpf("0.499999999999967859")
    C3=mpf("0.166666666666658858")
    C4=mpf("0.041666680841067401")
    C5=mpf("0.008333335853059549")
    gblic_exp = C0 + C1*x  + C2*(x**2) + C3*(x**3) + C4*(x**4) + C5*(x**5)
    return gblic_exp- exp(x)

# 定义一个使用mpf的函数
def my_exp_error_v1(x):
    C0 = mpf("1.0000000000000000000171013579411730")
    C1 = mpf("1.0000000000000000000146583067761690")
    C2 = mpf("0.4999999999999580113317076647134593")
    C3 = mpf("0.1666666666666540034175642630056476")
    C4 = mpf("0.0416666819398589745940878598721105")
    C5 = mpf("0.0083333362425128052522717020460354")
    myexp = C0 + C1*x  + C2*(x**2) + C3*(x**3) + C4*(x**4) + C5*(x**5)
    return myexp- exp(x)

def my_exp_error_v2(x):
    C0 = mpf("1.0")
    C1 = mpf("1.0000000000000000000112258035789583")
    C2 = mpf("0.4999999999999678437254515924663138")
    C3 = mpf("0.1666666666666552372523592190363665")
    C4 = mpf("0.0416666808432930432178558174251957")
    C5 = mpf("0.0083333361380779564483213034873581")
    myexp = C0 + C1*x  + C2*(x**2) + C3*(x**3) + C4*(x**4) + C5*(x**5)
    return myexp- exp(x)

def my_exp_error_v3(x):
    C0 = mpf("1.0")
    C1 = mpf("1.0")
    C2 = mpf("0.4999999999999678475773689815894736")
    C3 = mpf("0.1666666666666588604545019030700414")
    C4 = mpf("0.0416666808427005153548860243625152")
    C5 = mpf("0.0083333358527262326643806201825266")
    myexp = C0 + C1*x  + C2*(x**2) + C3*(x**3) + C4*(x**4) + C5*(x**5)
    return myexp- exp(x)

def my_exp_error_v4(x):
    C0 = mpf("0.9999999999999999999828522742909391")
    C1 = mpf("1.0000000000000002279646694875643681")
    C2 = mpf("0.4999999999995089360472388269970205")
    C3 = mpf("0.1666666670535088692190357349911896")
    C4 = mpf("0.0416665289339055680325209502558257")
    C5 = mpf("0.0083559302091520783584489479775211")
    myexp = C0 + C1*x  + C2*(x**2) + C3*(x**3) + C4*(x**4) + C5*(x**5)
    return myexp- exp(x)

def my_exp_error_v5(x):
    C0 = mpf("1.0")
    C1 = mpf("1.0")
    C2 = mpf("0.5")
    C3 = mpf("0.1666666667563876885313924940441920")
    C4 = mpf("0.0416665969635050692215652662272981")
    C5 = mpf("0.0083506570406799743127911743349753")
    myexp = C0 + C1*x  + C2*(x**2) + C3*(x**3) + C4*(x**4) + C5*(x**5)
    return myexp- exp(x)


def plot_exp_error(mode):

    # 定义x的范围
    ln2= mpf("0.69314718055994530941723212145817656807")

    k = ln2/mpf(256*500)
    if mode==0 or mode==1 or mode==2 or mode==3:
        x_values = [ mpf(i)*k for i in range(-500,501)]  # 从-500到500的整数
    else:
        x_values = [ mpf(i)*k for i in range(0,1001)]    # 从0到1000的整数

    # 计算对应的y值
    if mode==0:
        y_values = [glibc_exp_error(x) for x in x_values]
    elif mode==1:
        y_values = [my_exp_error_v1(x) for x in x_values]
    elif mode==2:
        y_values = [my_exp_error_v2(x) for x in x_values]
    elif mode==3:
        y_values = [my_exp_error_v3(x) for x in x_values]
    elif mode==4:
        y_values = [my_exp_error_v4(x) for x in x_values]
    else:
        y_values = [my_exp_error_v5(x) for x in x_values]

    # 绘制图像
    plt.plot(x_values, y_values)
    plt.xlabel('x')
    plt.ylabel('y')
    if mode==0:
        plt.title('glibc_exp(x)-exp(x)')
    elif mode==1:
        plt.title('exp_v1(x)-exp(x)')
    elif mode==2:
        plt.title('exp_v2(x)-exp(x)')
    elif mode==3:
        plt.title('exp_v3(x)-exp(x)')
    elif mode==4:
        plt.title('exp_v4(x)-exp(x)')
    else:
        plt.title('exp_v5(x)-exp(x)')

    plt.grid(True)
    plt.show()

plot_exp_error(0)
plot_exp_error(1)
plot_exp_error(2)
plot_exp_error(3)
plot_exp_error(4)
plot_exp_error(5)